ICTSC2019 一次予選 問題解説: 郷に入っては郷に従え
問題文
WEBサーバを運用する部署に所属することになったあなたは、前任者が構築したサーバを引き継ぐことになりました。現在の状態、発生した問題などについて、前任者の報告がありました。
LXCを使用してWEBサーバを構築しました。
コンテナではapacheが1234/tcpで起動しています。
LXCホストのiptablesでホスト80/tcpへの通信をコンテナ1234/tcpへ転送するDNATの設定をしました。
VNCサーバからLXCホストの80/tcpへアクセスすると無事にWEBサーバの起動を確認できました。
しかし、システムのアップデートをしようと思ったらコンテナからaptコマンドを使用できなくなりました。
どうやら、担当者は少々無理をしてコンテナのWEBサーバを外部に公開したようです。原因の究明と適切な設定を施してほしいです。設定は永続化し、再起動などが行えるようにしてください。
ゴール
- 外部(VNCサーバ)からLXCホスト80番でWEBページが確認できる(開始時点で閲覧可能だが、トラブルシューティング後も見られるようにすること)
- コンテナ内で
apt update
ができる - 設定の永続化が行われている
問題サーバー
- IPアドレス:
192.168.0.1
- ユーザー名:
admin
- パスワード:
3tRC7llZ
- サービス名:
dnat.service
- コンテナ名:
ubuntu-dnat
原因究明
iptablesのPREROUTINGチェインでDNATしているため、コンテナから外に出るときにもこのルールが適用されてしまう。
解説
現状の確認
初期状態だと、VNCサーバからLXCホスト80番でWEBページが確認できるのでまず確認してみる。
wget -O - 192.168.0.1
問題なくWEBページが公開できている。次に、問題サーバへ接続しスクリプトファイルを確認する。
#!/bin/bash
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.176.76.106:1234
どうやらsystemdを使ってiptablesを永続化させている。最後に発生している問題を確認する。
admin@lxc:~$ sudo lxc exec ubuntu-dnat /bin/bash
[sudo] password for admin:
root@ubuntu-dnat:~# apt update
Err:1 http://archive.ubuntu.com/ubuntu bionic InRelease
Cannot initiate the connection to archive.ubuntu.com:80 (2001:67c:1360:8001::21). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2001:67c:1560:8001::11). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2001:67c:1560:8001::14). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2001:67c:1360:8001::17). - connect (101: Network is unreachable) Could not connect to archive.ubuntu.com:80 (91.189.88.24), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.88.31), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.88.149), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.88.162), connection timed out
Err:2 http://archive.ubuntu.com/ubuntu bionic-updates InRelease
名前解決はできるが、HTTP接続に問題があるようだ。
解決方法
下記の2つ、どちらかのルールに変更すれば、コンテナから外に出る80/tcpがルールが掛からなくなります。これでapt updateが正常に実行できます。
- 公開しているネットワークのインターフェイス(th0)を指定する
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.176.76.106:1234
- destinationを指定してLXCホスト宛にのみDNATを行う
iptables -t nat -A PREROUTING -p tcp -d 192.168.0.1/24 --dport 80 -j DNAT --to-destination 10.176.76.106:1234
ここまでで、9割の解答になります。
適切な方法
上記の方法で問題は解決できますが、適切であるとは言えません。問題文にある無理やり
を解決する方法は以下の2つがあげれます。
-
lxc config
を使用する iptables-persistent
を使用するnginx
を使用する(想定外)
lxc configを使用した方法
そもそもLXCにはコンテナを外部に公開するコマンドが用意されています。この問題のタイトル郷に入っては郷に従え
はこの解法から決めました。
サービスの停止
sudo systemctl stop dnat.service
sudo systemctl disable dnat.service
lxc config でproxyを設定
sudo lxc config device add ubuntu-dnat http proxy listen=tcp:0.0.0.0:80 connect=tcp:10.176.76.106:1234 bind=host
iptables-persistentを使用した方法
本問題環境(ubuntu18)ではiptablesを永続化することはデフォルトではできません。そこでsystemdを使用して起動するたびにコマンドを実行していました。この点を無理やりと考えるとiptables-persistentを使用するのが適切です。
サービスを停止させます。
sudo systemctl stop dnat.service
sudo systemctl disable dnat.service
解決方法のルールを適応し、問題が解決している状態でiptables-persistentをインストールするとその状態で永続化されます。
sudo apt-get install iptables-persistent
nginxを使用した方法
あるチームが回答してくれた方法にnginxのリバースプロキシを使用する解法がありました。WEBを公開する手法として適切であると判断し、模範解答に追加しました。
admin@lxc:~$ cat /etc/nginx/conf.d/ictsc.conf
server{
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://10.176.76.106:1234;
}
}
採点基準
- apt get が使用できる状態になっており、回答にコマンドと説明が記述されている :140点
- 原因を究明し、回答に記述されている :40点
- 適切な手法で解決し、回答に記述されている :20点